/*
 * Copyright 2012-2014 Finbudget.com
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package finbudget.client.ui.table;

import java.io.Serializable;

import com.google.gwt.user.client.rpc.IsSerializable;

import finbudget.client.lists.GetListOfItems.ListType;
import finbudget.client.ui.table.fields.actions.DependentAction;
import finbudget.client.ui.table.fields.dependences.FieldDependence;

public class Field implements IsSerializable, Serializable, Transformable {
	private static final long serialVersionUID = -671766218436717476L;
	/**
	 * Marker for node's property that stores forms fields.
	 */
	public static final String tagFields = "fields";
	/**
	 * Marker for node's property that stores buttons shown in the table form.
	 */
	public static final String tagButtons = "buttons";

	public static enum Type implements IsSerializable, Serializable {
		LONG,
		SUBMIT,
		STRING,
		DESCRIPTION,
		DESCRIPTIONINPLACE,
		DATE,		// the value passed as a formatted date 2011-10-07
		DATETIME,	// the value passed as long
		LIST,
		LISTADDABLE,
		SUGGEST,
		SUGGESTADDABLE,	// the field of this type must have SuggestAddableField class
		ATTACHMENT,
		BOOL,
		STATIC,
		BIGDECIMAL,
		MENULIST,	// the field of this type must have MenuListField class
		MENUBLOCK,	// the field of this type must have MenuBlockField class
		SEPARATOR,	// the field of this type must have SeparatorField class
		LINK,		// the field of this type must have LinkField class
		TRIPPLE, 	// Allows True, False, null values.
		HTML,
		PERMISSION,	// Permission edit field
		LINKS,		// the field of this type must have LinksField class
		MENUICON,	// the field of this type must have MenuIconField class
		MENUGROUP,	// the field of this type must have MenuGroupField class
		TABLEBODY,	// the field of this type must have TableBodyField class
	}
	public Type type;
	/**
	 * Field caption in Form view.
	 */
	public String captionForm;
	/**
	 * Field caption in Grid view.
	 */
	public String captionGrid;
	/**
	 * Row to place the control in Form view.
	 */
	public int row;
	/**
	 * Column to place the control in Grid view.
	 */
	public int column;
	public int colspan;
	public int rowspan;
	public String id;
	/**
	 * If the field is required then required member
	 * contains error message to show when the field1
	 * is not filled.
	 */
	public String required;
	/**
	 * The type of list to be shown in Form view.
	 */
	public ListType listTypeForm;
	/**
	 * The type of list to be shown in Grid view.
	 */
	public ListType listTypeGrid;
	/**
	 * Flag if not to cleanup the field in the form
	 * after a new element was saved. Default is false:
	 * the field is cleaned up.
	 * The proper name of this member field is 'can fix value'.
	 */
	public boolean dontCleanupAfterNewSaved;
	public boolean readOnly;
	public boolean noFilter;
	public String placeholder;
	private FieldDependence dependence;
	private DependentAction dependentAction;
	private String width;
	/**
	 * This member is used to initialize tables. In case this member is false then the column
	 * initially is not visible.
	 */
	private boolean isHiddenByDefault;
	private boolean indexed;

	/** Serialization requirements */
	public Field() {
	}

	public static Field getSuggestField(String id, String name, int row, int col, ListType listType, String required) {
		Field field = new Field();
		field.type = Type.SUGGEST;
		field.id = id;
		field.captionForm = name;
		field.captionGrid = name;
		field.row = row;
		field.column = col;
		field.listTypeForm = listType;
		field.listTypeGrid = listType;
		field.required = required;
		return field;
	}

	public static Field getBigDecimalField(String id, String name, int row, int col, String required) {
		Field field = new Field();
		field.type = Type.BIGDECIMAL;
		field.id = id;
		field.captionForm = name;
		field.captionGrid = name;
		field.row = row;
		field.column = col;
		field.required = required;
		return field;
	}

	public static Field getField(String id, Type type, String name, int row, int col) {
		Field field = new Field();
		field.type = type;
		field.id = id;
		field.captionForm = name;
		field.captionGrid = name;
		field.row = row;
		field.column = col;
		return field;
	}

	public Field setRowSpan(int rowspan) {
		this.rowspan = rowspan;
		return this;
	}

	public Field setColumnSpan(int colspan) {
		this.colspan = colspan;
		return this;
	}

	public Field setRequired(String required) {
		this.required = required;
		return this;
	}

	public Field setReadOnly(boolean readOnly) {
		this.readOnly = readOnly;
		return this;
	}

	public boolean isCanFixValue() {
		return dontCleanupAfterNewSaved;
	}

	public Field setCanFixValue(boolean canFixValue) {
		this.dontCleanupAfterNewSaved = canFixValue;
		return this;
	}

	public Field setType(ListType type) {
		this.listTypeForm = type;
		this.listTypeGrid = type;
		return this;
	}

	public Field setPlaceholder(String placeholder) {
		this.placeholder = placeholder;
		return this;
	}

	/**
	 * If the field value depends on the value of another field(s)
	 * this method allows to set up this dependence.
	 * @param dependence
	 * @return
	 */
	public Field setDependence(FieldDependence dependence, DependentAction dependentAction) {
		this.dependence = dependence;
		this.dependentAction = dependentAction;
		return this;
	}

	public FieldDependence getDependence() {
		return dependence;
	}

	public DependentAction getDependentAction() {
		return dependentAction;
	}

	public String getWidth() {
		return width;
	}

	public Field setWidth(String width) {
		this.width = width;
		return this;
	}

	public boolean isHiddenByDefault() {
		return isHiddenByDefault;
	}

	public Field setHiddenByDefault(boolean isHiddenByDefault) {
		this.isHiddenByDefault = isHiddenByDefault;
		return this;
	}

	public String getId() {
		return id;
	}

	public Field setIndexed(boolean indexed) {
		this.indexed = indexed;
		return this;
	}
	@Override
	public boolean isIndexed() {
		return indexed;
	}

	@Override
	public Object toRaw(Transformator transformator, Object value) {
		return transformator.toRaw(this, value);
	}

	@Override
	public String fromRaw(Transformator transformator, Object value) {
		return transformator.fromRaw(this, value);
	}

}
